import { ContextItem } from './LingmaContext';
import { LingmaSDKTool } from './LingmaSDKTool';

/**
 * Lingma Programming Assistant Preprocessing Interface
 * @param request User sent request
 * @param SDKTool SDK Tool Class, through which information related to IDE and Plugin can be obtained
 * @returns Return result after preprocessing
 */
export interface RequestPreHandler {
  // Preprocessing method
  handle: (request: RawRequest, SDKTool: LingmaSDKTool) => Promise<PreHandlerResponse>;
}

/**
 * Lingma Programming Assistant Postprocessing Interface
 * @param request User sent request
 * @param response Inference content returned by LLM
 * @param SDKTool SDK Tool Class, through which information related to IDE and Plugin can be obtained
 * @returns Return result after postprocessing
 */
export interface RequestPostHandler {
  // Postprocessing method
  handle: (request: RawRequest, response: AIResponse, SDKTool: LingmaSDKTool) => Promise<PostHandlerResponse>;
}


/**
 * Request object definition, request includes the triggered behavior and raw data to be sent to LLM
 */
export interface RawRequest {
  // Unique identifier of the current request, can be used to trace request execution
  action: ActionEnum;
  // Trigger request behavior enumeration
  payload: ContentPayload;
  // Encapsulate raw data content payload
  requestId: string;
}

/**
 * Preprocessing Result
 */
export class PreHandlerResponse {
  // Handling strategy, through which subsequent processing logic can be controlled
  handlePolicy: HandlePolicy;
  // Reason description
  reason?: string;
  // When handlePolicy=FILTER, this attribute needs to be set, its value is the filtered data (must be consistent with ContentRequest.payload content)
  payload?: ContentPayload;
  constructor() {
    // Default values
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    this.handlePolicy = HandlePolicy.NO_OPS;
    this.reason = '';
    this.payload = new ContentPayload();
  }
}

/**
 * Postprocessing Result
 */
export class PostHandlerResponse {
  // Handling strategy, through which subsequent processing logic can be controlled
  handlePolicy: HandlePolicy;
  // Reason description
  reason?: string;
  // Model return result processed by postprocessor
  processedResult: InferredResult;
  constructor() {
    // Default values
    this.handlePolicy = HandlePolicy.NO_OPS;
    this.reason = '';
    this.processedResult = new InferredResult();
  }
}

/**
 * Encapsulate the return result of the large model
 */
export class AIResponse {
  // Model inference result
  inferredResult: InferredResult;
  constructor() {
    this.inferredResult = new InferredResult();
  }
}

/**
 * Model inference generated result data
 */
export class InferredResult {
  // Text content generated by LLM
  text: string;
  constructor() {
    this.text = '';
  }
}
/**
 * Encapsulate the original data content sent to LLM
 */
export class ContentPayload {
  // Data collection to be processed, corresponding key reference ContextValueKeyEnum definition
  data: Map<PayloadDataKeyEnum, PayloadDataValueType>;
  // Context associated with processing
  associatedContexts: ContextItem[];

  constructor() {
    this.data = new Map<PayloadDataKeyEnum, PayloadDataValueType>();
    this.associatedContexts = [];
  }
}


/**
 * ContentPayload.data key enumeration
 */
export enum PayloadDataKeyEnum {
  // Code snippet selected by the user
  SELECTED_CODE ='lingma:code',
  // Text input by the user
  USER_INPUT = 'lingma:text',
  // Error messages
  ERROR_MESSAGES = 'lingma:error_messages',
  // Log information printed in the terminal
  TERMINAL_CONTENT = 'lingma:terminal_content',
  // Prefix code snippet when code completion, code snippet before the cursor in the current line
  PREFIX_CODE = 'lingma:code_prefix',
  // Suffix code snippet when code completion, code snippet after the cursor in the current line
  SUFFIX_CODE = 'lingma:code_suffix',
  // Similar code snippets
  SIMILAR_CODE = 'lingma:similar_code',
  // File path where completion is executed in completion scenario
  FILE_PATH = 'lingma:file_path',
}

// ContentPayload.data value type
export type PayloadDataValueType = string | number | string[];

/**
 * Trigger request behavior enumeration
 */
export enum ActionEnum {
  // Unit test
  GENERATE_TESTCASE = 'GENERATE_TESTCASE',
  // Generate comments
  CODE_GENERATE_COMMENT = 'CODE_GENERATE_COMMENT',
  // Code explanation
  EXPLAIN_CODE = 'EXPLAIN_CODE',
  // Code optimization
  OPTIMIZE_CODE = 'OPTIMIZE_CODE',
  // Free input (i.e., directly input text in the question and answer input box)
  FREE_INPUT = 'FREE_INPUT',
  // Quick fix for code issues
  CODE_PROBLEM_SOLVE = 'CODE_PROBLEM_SOLVE',
  // Shell command generation
  TERMINAL_COMMAND_GENERATION = 'TERMINAL_COMMAND_GENERATION',
  // Terminal error fix
  TERMINAL_EXPLAIN_FIX = 'TERMINAL_EXPLAIN_FIX',
  // Code completion
  COMPLETION = 'COMPLETION',
}

/**
 * Handling strategy enumeration
 */
export enum HandlePolicy {
  // Block strategy, directly block the request
  BLOCK = 'BLOCK',
  // Filter strategy, intercept the request and modify the payload content
  FILTER = 'FILTER',
  // Ignore strategy, do not process the request
  NO_OPS = 'NO_OPS',
}
